package com.lkl.chat.server;

import com.google.gson.Gson;
import com.lkl.chat.config.SparkConfig;
import com.lkl.chat.model.dto.ChatRequest;
import com.lkl.chat.model.entity.SparkChat;
import com.lkl.chat.socket.SparkChatListener;
import com.lkl.chat.util.AuthorUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import javax.swing.*;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Data
@Slf4j
@Component
public class SparkManager {

    @Resource
    private SparkConfig sparkConfig;

    @Value("${spark.defaultHostInfo.host}")
    private String host;
    @Value("${spark.defaultHostInfo.path}")
    private String path;
    @Value("${spark.defaultHostInfo.domain}")
    private String domain;
    @Value("${spark.appid}")
    private String appid;
    @Value("${spark.apiSecret}")
    private String apiSecret;
    @Value("${spark.apiKey}")
    private String apiKey;

    public String doChat(String userId,String question) throws Exception {
        log.info("开始聊天,{},{}",userId,question);
        // 构建鉴权url
        String authUrl = AuthorUtil.genAuthUrl(apiKey, apiSecret, host, path);
        OkHttpClient client = new OkHttpClient.Builder().build();
        // 构建websocket请求
        Request request = new Request.Builder().url(authUrl).build();
        SparkChat sparkChat = new SparkChat(sparkConfig, userId,question);
        // 发起websocket请求
        WebSocket webSocket = client.newWebSocket(request,sparkChat );
        String chatRequest = buildChatRequest(appid, domain, userId, question);
        //发送消息
        webSocket.send(chatRequest);
        // 等待websocket关闭
        while (!sparkChat.getWsCloseFlag()) {
            Thread.sleep(100);
        }
        return sparkChat.getTotalAnswer().toString();
    }
    // 用来缓存 用户的SseEmitter
    private static final Map<Object, SseEmitter> SSE_CACHE = new ConcurrentHashMap<>();
    public SseEmitter getConn(Object key) {
        final SseEmitter sseEmitter = SSE_CACHE.get(key);
        if (sseEmitter != null) {
            return sseEmitter;
        } else {
            // 设置连接超时时间，需要配合配置项 spring.mvc.async.request-timeout: 600000 一起使用
            final SseEmitter emitter = new SseEmitter(600000L);
            // 注册超时回调，超时后触发
            emitter.onTimeout(() -> {
                log.info("连接已超时，正准备关闭，key = {}", key);
                SSE_CACHE.remove(key);
            });
            // 注册完成回调，调用 emitter.complete() 触发
            emitter.onCompletion(() -> {
                log.info("连接已关闭，正准备释放，key = {}", key);
                SSE_CACHE.remove(key);
                log.info("连接已释放，key = {}", key);
            });
            // 注册异常回调，调用 emitter.completeWithError() 触发
            emitter.onError(throwable -> {
                log.error("连接已异常，正准备关闭，key = {}", key, throwable);
                SSE_CACHE.remove(key);
            });
            SSE_CACHE.put(key, emitter);
            return emitter;
        }
    }
    public SparkChatListener doChat(String userId, String question, StringBuilder answer) {
        // 构建鉴权url
        String authUrl = AuthorUtil.genAuthUrl(sparkConfig.getApiKey(), sparkConfig.getApiSecret(),
                sparkConfig.getDefaultHostInfo().getHost(), sparkConfig.getDefaultHostInfo().getPath());
        if (authUrl == null) {
            throw new RuntimeException("authUrl 生成失败 !");
        }
        OkHttpClient client = new OkHttpClient.Builder().build();
        // 构建聊天请求
        String chatRequest = buildChatRequest(appid, domain, userId, question);

        // 构建websocket请求
        Request request = new Request.Builder().url(authUrl).build();
        SparkChatListener sparkChat = new SparkChatListener(answer);
        // 发起websocket请求
        WebSocket webSocket = client.newWebSocket(request, sparkChat);
        webSocket.send(chatRequest);
        return sparkChat;
    }


    /**
     * 构建聊天请求
     * @return 聊天请求
     */
    private String buildChatRequest(String appid,String domain,String userId,String question) {
        ChatRequest chatRequest = ChatRequest.builder()
                .header(ChatRequest.Header.builder()
                        .app_id(appid)
                        .uid(userId)
                        .build())
                .parameter(ChatRequest.Parameter.builder()
                        .chat(ChatRequest.Chat.builder()
                                .domain(domain)
                                .temperature(0.5)
                                .max_tokens(4096)
                                .build())
                        .build())
                .payload(ChatRequest.Payload.builder()
                        .message(ChatRequest.Message
                                .builder()
                                .text(Collections.singletonList(
                                        ChatRequest.Text.builder()
                                                .content(question)
                                                .role("user")
                                                .build()))
                                .build())
                        .build()).build();
        return new Gson().toJson(chatRequest);
    }

}
